package org.dbpt.performance;

import java.sql.Connection;
import java.sql.ParameterMetaData;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.List;

import javax.sql.DataSource;

public class SQLExecutor {

	private DataSource dataSource;
	private Connection connection;
	private String sql;
	private int count = 1;
	private int countPerTransaction = 1;
	private String description;
	private List<ParamGenerator> paramGenerators;

	public List<ParamGenerator> getParamGenerators() {
		return paramGenerators;
	}

	public void setParamGenerators(List<ParamGenerator> paramGenerators) {
		this.paramGenerators = paramGenerators;
	}

	public String getDescription() {
		return description;
	}

	public void setDescription(String description) {
		this.description = description;
	}

	public int getCountPerTransaction() {
		return countPerTransaction;
	}

	public void setCountPerTransaction(int countPerTransaction) {
		this.countPerTransaction = countPerTransaction;
	}

	public String getSql() {
		return sql;
	}

	public void setSql(String sql) {
		this.sql = sql;
	}

	public int getCount() {
		return count;
	}

	public void setCount(int count) {
		this.count = count;
	}

	public DataSource getDataSource() {
		return dataSource;
	}

	public void setDataSource(DataSource dataSource) {
		this.dataSource = dataSource;
	}

	public Connection getConnection() {
		return connection;
	}

	public void setConnection(Connection connection) {
		this.connection = connection;
	}

	public void start() {
		Connection con;
		if (description != null) {
			System.out.println(description);
		}
		try {
			con = dataSource.getConnection();
			con.setAutoCommit(false);
			PreparedStatement ps = con.prepareStatement(sql);
			long t1 = System.currentTimeMillis();
			for (int i = 0; i < count; i++) {
				for (int k = 0; k < countPerTransaction; k++) {

					ParameterMetaData metadata = ps.getParameterMetaData();
					int paramCount = metadata.getParameterCount();
					for (int j = 0; j < paramCount; j++) {
						if (paramGenerators == null || paramGenerators.size() == 0) {
							String className = metadata
									.getParameterClassName(j + 1);
							if (String.class.getName().equals(className)) {
								ps.setString(j + 1,
										DataGenerator.generateString(50));
							} else if (int.class.getName().equals(className)
									|| Integer.class.getName()
											.equals(className)) {
								ps.setInt(j + 1,
										DataGenerator.generateInt(1000));
							}
						} else {
							int genIdx = j;
							if(genIdx >= paramGenerators.size()) 
								genIdx = paramGenerators.size() - 1;
							paramGenerators.get(genIdx).generate(ps, j + 1);
						}
					}
					ps.execute();
					
				}
				con.commit();
			}
			long t2 = System.currentTimeMillis();
			long t = t2 - t1;
			double psec = (double) count * countPerTransaction / t;

			String msg = String
					.format("Time = %dms\nCount = %d\nCount per transaction = %d\nPermormance = %2f K/sec\n\n",
							t, count, countPerTransaction, psec);
			System.out.println(msg);
			con.close();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}
